/**
 * 
 */
package com.dfhc.util.aes;

import java.util.ArrayList;
import java.util.List;

import com.dfhc.util.StringHelper;

/**
 * @author 龙色波
 * 编码
 */
public class Base64 {
	private char[] chars;
	private String _chars;

	public Base64(){
		_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
		chars = _chars.toCharArray();		
	}
	/**
	 * 将字节数组转换为字符串
	 * @param cipherBlocks
	 * @param withBreaks
	 * @return
	 */
	public String encode(int[][] cipherBlocks,boolean withBreaks){
		Integer flatArr[] = new Integer[cipherBlocks.length*16];
	    String b64 = "";
	    int i;
//        String broken_b64;
        
	    //totalChunks = Math.floor(b.length * 16 / 3);
        for (i = 0; i < cipherBlocks.length * 16; i++) {
            flatArr[i]=(cipherBlocks[ (int) Math.floor(i / 16)][i % 16]);
        }
        for (i = 0; i < flatArr.length; i = i + 3) {
            b64 += chars[flatArr[i] >> 2];
            int index = 0;
            if(i+1<flatArr.length){
            	index = ((flatArr[i] & 3) << 4) | (flatArr[i + 1] >> 4);
            }else{
            	index = ((flatArr[i] & 3) << 4) | 0;
            }
//            if(index>=chars.length){
//            	System.out.println("i:"+i+",index:"+index);
//            }
			b64 += chars[index];
            if (i+1<flatArr.length &&  flatArr[i + 1] != null ) {
            	if(i+2>=flatArr.length){
            		b64 += chars[((flatArr[i + 1] & 15) << 2)];
            	}else{
            		b64 += chars[((flatArr[i + 1] & 15) << 2) | (flatArr[i + 2] >> 6)];
            	}
            } else {
                b64 += '=';
            }
            if(i+2<flatArr.length){
	            if ( flatArr[i + 2] != null ) {
	                b64 += chars[flatArr[i + 2] & 63];
	            } else {
	                b64 += '=';
	            }
            }else{
            	b64 += '=';
            }
        }
        // OpenSSL is super particular about line breaks
        //去掉行断，否则某些aes js无法解密
//        broken_b64 = b64.substring(0, b64.length()>=64?64:b64.length()) + '\n';
//        double d = b64.length() / 64d;
//        for (i = 1; i < (Math.ceil(d)); i++) {
//        	if(i*64+64<b64.length()){
//        		broken_b64 += b64.substring(i * 64, i * 64 + 64) + (Math.ceil(d) == i + 1 ? "": '\n');
//        	}else{
//        		broken_b64 += b64.substring(i * 64) + (Math.ceil(d) == i + 1 ? "": '\n');
//        	}
//        }
//        return broken_b64;	
        return b64;
	}
	public int[] decode (String string) {
         string = StringHelper.replaceAll(string, "\n", "").toString();
         List<Integer> flatArr = new ArrayList<Integer>();
         int c[] = new int[4];
         int b[]= new int[4];
         int i;
         for (i = 0; i < string.length(); i = i + 4) {
             c[0] =  _chars.indexOf(string.charAt(i));
             if(i+1<string.length()){
            	 c[1] =  _chars.indexOf(string.charAt(i + 1));
             }else{
            	 c[1]=0;             
             }
             if(i+2<string.length()){
            	 c[2] =  _chars.indexOf(string.charAt(i + 2));
             }else{
            	 c[2] = 0;
             }
             if(i+3<string.length()){
            	 c[3] =  _chars.indexOf(string.charAt(i + 3));
             }else{
            	 c[3] = 0;
             }

             b[0] =  ((c[0] << 2) | (c[1] >> 4));
             b[1] =  (((c[1] & 15) << 4) | (c[2] >> 2));
             b[2] =  (((c[2] & 3) << 6) | c[3]);
             flatArr.add(b[0]);
             flatArr.add(b[1]);
             flatArr.add(b[2]);
         }
         int retBytes[] = new int[flatArr.size() - (flatArr.size() % 16)];
         //flatArr = flatArr.slice(0, flatArr.length - (flatArr.length % 16));
         for(i=0;i<retBytes.length;i++){
        	 retBytes[i] = flatArr.get(i);
         }
         return retBytes;
     }
}
